/* 
 *
 * Persistence4J - Simple library for data persistence using java
 * Copyright (c) 2010, Avdhesh yadav.
 * http://www.avdheshyadav.com
 * Contact: avdhesh.yadav@gmail.com
 *
 * This library is free software; you can redistribute it and/or modify it under the terms
 * of the GNU Lesser General Public License as published by the Free Software Foundation,
 * either version 3 of the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
 * without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
 * See the GNU Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public License along with this
 * library; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330,
 * Boston, MA 02111-1307, USA.
 *
 */
package com.avdy.p4j.jdbc.dbms;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;

import javax.transaction.UserTransaction;

import org.apache.log4j.Logger;

import com.avdy.p4j.common.DAOException;
import com.avdy.p4j.jdbc.PersistenceConfig;
import com.avdy.p4j.jdbc.dao.AbsPersistenceManager;
import com.avdy.p4j.jdbc.dbms.connfactory.ConnectionFactory;
import com.avdy.p4j.jdbc.dbms.connfactory.DBConnector;
import com.avdy.p4j.jdbc.dbms.connfactory.XaDBConnector;
import com.avdy.p4j.jdbc.dbms.metadata.IMetaDataLoader;


/**
 * @author Avdhesh Yadav   
 */
abstract class Dbms 
{
	static Logger logger = Logger.getLogger(Dbms.class.getName());
	
	protected String m_XaApiProvider;
	
	protected PersistenceConfig mConfig;

	protected Map<String, AbsPersistenceManager> m_PcManagerMap;
	
	protected ConnectionFactory m_ConnFactory;
	
	protected DataSourceAttr mDsAttr;
	
	/**
	 * 
	 */
	public Dbms(PersistenceConfig config)
	{
		mConfig = config;
		m_PcManagerMap = new HashMap<String, AbsPersistenceManager>();
		m_XaApiProvider = mConfig.getXaApiProvider();
	}


	/**
	 *  
	 * @param dbms String
	 * 
	 * @return DataSourceAttr
	 */
	public DataSourceAttr constructDataSourceAttr(String dbms)
	{
		String driver   = mConfig.getDatabaseDriver(dbms);
		String hostName = mConfig.getHostName(dbms);
		int port 	   = mConfig.getDataBasePort(dbms);
		String username = mConfig.getUserName(dbms);
		String password = mConfig.getPassword(dbms);
		int minPool  = mConfig.getMinPool(dbms);
		int maxPool  = mConfig.getMaxPool(dbms);
		String xaDataSourceClassName = mConfig.getXaDataSourceClassName(dbms);
		mDsAttr = new DataSourceAttr(driver,hostName,port,username,password,xaDataSourceClassName);
		mDsAttr.setMinPoolSize(minPool);
		mDsAttr.setMinPoolSize(maxPool);
		return mDsAttr;
	}
	
	
	/**
	 * 	
	 * @param database String
	 * 
	 * @return AbsPersistenceManager String
	 * 
	 * @throws Exception
	 */
	public  AbsPersistenceManager getPCManager(String database) throws DAOException
	{
		if(m_PcManagerMap.containsKey(database))
		{
			return  m_PcManagerMap.get(database);
		}
		else
		{
			throw new DAOException("DataSource is not Found:"+database);
		}
	}
	
	
	/**
	 * 
	 * @param database String
	 * 
	 * @return UserTransaction
	 * 
	 * @throws Exception
	 */
	public UserTransaction getTMService(String database, final boolean isTransactional) throws DAOException
	{
		UserTransaction ut = null;
		AbsPersistenceManager pcManager = m_PcManagerMap.get(database);
		if(pcManager != null)
		{
			if(isTransactional)
			{
				IMetaDataLoader loader = pcManager.getMetaDataLoader();
				XaDBConnector connector = (XaDBConnector)loader.getDBConnector();
				ut = connector.getUserTransaction();
			}
		}
		else
		{
			String errMsg = "This database is not found:" + database;
			logger.info(errMsg);
			throw new DAOException(errMsg);
		}
		return ut;
	}
	
	
	/**
	 * 
	 * @param database String
	 * 
	 * @throws Exception
	 */
	public abstract void createDataSource(String database, final boolean isTransactional) throws Exception;

	
	/**
	 * 
	 * @return List
	 */
	public List<String> listDataSources()
	{
		List<String> datasources = new ArrayList<String>();
		
		Set<String> keys = m_PcManagerMap.keySet();
		
		for(String database : keys)
		{
			datasources.add(database);
		}
		return datasources;
	}
	
	
	/**
	 * 
	 * @param database String
	 * 
	 * @throws DAOException
	 */
	public void unBindDatasource(String database)throws DAOException
	{
		logger.info("undindDatasource:"+database);
		AbsPersistenceManager pcManager = m_PcManagerMap.get(database);

		if(pcManager != null)
		{
			DBConnector connector = pcManager.getDBConnector();
			if(connector != null)
				connector.stop();
		}
		else
		{
			throw new DAOException("database Does not Exist.:" + database);
		}
		
		m_PcManagerMap.remove(database);
		logger.info(database + " database unbinded sucessfully");
	}

	
	/**
	 * 
	 * @param database String
	 * 
	 * @return boolean
	 * 
	 */
	protected boolean isNewDataSource(String database)
	{
		boolean isNew = true;
		System.out.println("m_PcManagerMap:"+m_PcManagerMap);
		if(m_PcManagerMap.containsKey(database))
		{
			isNew = false;
		}
		return isNew;
	}
	
	
	/**
	 * here we test weather the Database connector is transactional or non-transactional
	 * @param database String
	 * 
	 * @return DBConnector
	 * 
	 * @throws Exception
	 */
	protected DBConnector getDBConnector(String database, boolean isTransactional) throws Exception
	{
		DBConnector connector = null;
		//here we test weather the Database connector is transactional or non-transactional
		if(isTransactional)
		{
			connector = m_ConnFactory.newXADBConnector(m_XaApiProvider, database, mDsAttr);
		}
		else
		{
			connector = m_ConnFactory.newNonXADBConnector(database, mDsAttr);
		}
		return connector;
	}
}